-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Implements a cache for train collision checks for better performance #9513
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mc1.21.1/dev
Are you sure you want to change the base?
Implements a cache for train collision checks for better performance #9513
Conversation
|
If this works properly this is brilliant @stacode123 and definately needed. We've turned train collisions off entirely to help with lag but thats definately not a fix most servers want to implement. Using Copilot is a little worrying though because you need to know exactly whats going on for this. Make sure you've tested it thoroughly and used the debugger to step through the code to see whats going on and if it aligns with what you expect. |
Jozufozu
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very excited about this and the spark profile is extremely promising. A 5mspt difference is huge
How many trains did you use in your test world? It would be helpful to upload a screenshot of the chaos 😆
Also after the requested changes and before this merges I'd like to request a longer profile to compare. I'm a little nervous the 16 second profiles may not have enough signal to noise
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
| if (length > 0.0001) { | ||
| direction[index] = diff.normalize(); | ||
| } else { | ||
| direction[index] = Vec3.ZERO; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will this happen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you've removed this but please justify it
|
To be honest it's rare u see such a stark contrast between before and after. A similar number of players are connected to the server as well so the difference likely isn't down to that. :) |
…llisionCache calls.
|
@Jozufozu Please review the changes :D |
|
|
||
| Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph); | ||
| Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph); | ||
| Vec3 start = collisionCache.start[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did the speed < 0 checks go? If the train is moving backwards we need to check for collisions with the trailing end as if it were the head
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh also do we know for sure that the collision cache is non-null here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- That is handled when collision cache is created.
- Earlier in the train tick we updated the collision cache but i can add a null check just to be sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I do not see anything in this function that would indicate the order of the cache is reversed based on speed https://github.com/Creators-of-Create/Create/pull/9513/files#diff-671a8e994774f6be471b30fd8459587f56fd246119f83bb82b47b47e0056608cR646
- Earlier in the train tick we potentially invalidate the cache, leaving it null
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
| if (length > 0.0001) { | ||
| direction[index] = diff.normalize(); | ||
| } else { | ||
| direction[index] = Vec3.ZERO; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you've removed this but please justify it
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
src/main/java/com/simibubi/create/content/trains/entity/Train.java
Outdated
Show resolved
Hide resolved
| for (Train train : movingTrains){ | ||
| train.updateCollisionCache(); | ||
| train.earlyTick(level);} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
formatting please
for (Train train : movingTrains) {
train.updateCollisionCache();
train.earlyTick(level);
}do we not need the collision cache for waiting trains? do we not expect moving trains to collide with trains that are stationary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wont stationary trains have already built up cache ? And trying to calculate it again would just yield the same result?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about on initial level load? Can we really assume that a train that just became stationary this tick will have valid positions in the cache from the previous tick where it was moving?
Still, that's a good point. If you're feeling ambition you could probably check some easy to compute value at the start of updateCollisionCache to see if the train has moved from the previous tick and decide whether to update the collision cache. If you do though, I'd like to see proof that it works and waiting trains still get collided with
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 Initial level load will have the cache empty, causing it to update at the start of the collision checks.
2. I think so? we have been running the build on our server with no issues for now.
3. That would the best direction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Where will it update? On this line you specifically skip trains that do not have a collision cache: https://github.com/Creators-of-Create/Create/pull/9513/files#diff-671a8e994774f6be471b30fd8459587f56fd246119f83bb82b47b47e0056608cR732
- I believe it doesn't crash or anything, but I'm not convinced that there aren't false negatives in the collision checks under the current iteration of this PR
- I agree, do it
| if (derailed || graph == null) { | ||
| if (collisionCache != null) | ||
| collisionCache.invalidate(); | ||
| collisionCache = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably don't need the collisionCache != null check anymore. just assigning is fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you mean by that
| private void updateCollisionCache() { | ||
| if (derailed || graph == null) { | ||
| if (collisionCache != null) | ||
| collisionCache.invalidate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment in the code please
| // | ||
| if (derailed || graph == null) { | ||
| if (collisionCache != null) | ||
| collisionCache = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we still be setting this to null before returning?
This is why I asked you to explain why it was being set to null here, so that future maintainers can understand the intention.
My understanding of your intention is that a null collision cache means there is nothing valid to collide with. Here you explicitly leave a cache with potentially stale positions in a valid state
|
|
||
|
|
||
| public void updateCollisionCache() { | ||
| // |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to write something here?
| collisionCache = new CollisionCache(maxExpectedSegments); | ||
| } | ||
|
|
||
| //For adding segments between carriages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// For adding segments between carriages
Leave a space after the // please
| continue; | ||
| if (train.graph != null && train.graph != graph) | ||
| continue; | ||
| if (train.collisionCache == null) {continue;} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Formatting
if (train.collisionCache == null)
continue;or
if (train.collisionCache == null) {
continue;
}but be consistent
| for (Train train : movingTrains){ | ||
| train.updateCollisionCache(); | ||
| train.earlyTick(level);} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Where will it update? On this line you specifically skip trains that do not have a collision cache: https://github.com/Creators-of-Create/Create/pull/9513/files#diff-671a8e994774f6be471b30fd8459587f56fd246119f83bb82b47b47e0056608cR732
- I believe it doesn't crash or anything, but I'm not convinced that there aren't false negatives in the collision checks under the current iteration of this PR
- I agree, do it
|
|
||
| Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph); | ||
| Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph); | ||
| Vec3 start = collisionCache.start[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I do not see anything in this function that would indicate the order of the cache is reversed based on speed https://github.com/Creators-of-Create/Create/pull/9513/files#diff-671a8e994774f6be471b30fd8459587f56fd246119f83bb82b47b47e0056608cR646
- Earlier in the train tick we potentially invalidate the cache, leaving it null
|
|
||
| Vec3 start = (speed < 0 ? trailingPoint : leadingPoint).getPosition(graph); | ||
| Vec3 end = (speed < 0 ? leadingPoint : trailingPoint).getPosition(graph); | ||
| if (collisionCache == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do this here if all trains are supposed to have it baked ahead of time here?
https://github.com/Creators-of-Create/Create/pull/9513/files#diff-f2e214ec2c56dc28c4a2596c6113202b29392f9dc209be510cce0bed03be4042R222




Implements a cache for train collision checks for better performance
Before: https://spark.lucko.me/cgjtsUl25f
After: https://spark.lucko.me/p7ZcDxAUFA
Criticism welcome.
Made with the help of Copilot
World used for testing :
world.zip